/*
Wrapper for the Windows Logocal Drives
Version: 1.0
Modified on: 8-20-2009
Created with: QT 4.5 and QT Creator 1.2
Tested on: Windows XP SP3
Bryan Cairns
*/

#include "vdrives.h"
#include "windows.h"
#include "VQTConvert.h"
#include <QString>
#include <QStringList>
#include <QDebug>

namespace voidrealms
{
    namespace win32
    {

        //Default constructor
        VDrives::VDrives(){this->mVolumeSerialNumber = 0;}
        VDrives::VDrives(QString LogicalDrive)
        {
            //Make sure the drive is formatted correctly
            mDrive = LogicalDrive;
            mDrive = mDrive.replace("/","\\");
            if(mDrive.endsWith("\\") == false)
            {
                mDrive += "\\";
            }

            //load information about the drive
            LoadDriveInfo();

            //Get the drive Type;
        }

        //Load the drives information
        void VDrives::LoadDriveInfo()
        {
            bool lResult;
            LPCTSTR RootPath = VQTConvert::QString_To_LPCTSTR(this->mDrive); //QString_To_LPCTSTR(this->mDrive);
            DWORD dwLabelSize = MAX_PATH + 1;
            DWORD dwFileSystemSize = MAX_PATH + 1;
            WCHAR* pLabel = new WCHAR[dwLabelSize];
            WCHAR* pFileSystem = new WCHAR[dwFileSystemSize];
            DWORD VolumeSerialNumber;
            DWORD MaximumComponentLength;
            DWORD FileSystemFlags;

            //Get information about the Drives Label and File System
            lResult = GetVolumeInformation(RootPath,pLabel,dwLabelSize,&VolumeSerialNumber,&MaximumComponentLength,&FileSystemFlags,pFileSystem,dwFileSystemSize);

            if(lResult)
            {
                this->mLabel = VQTConvert::WCHAR_to_QString(pLabel);
                this->mFileSystem = VQTConvert::WCHAR_to_QString(pFileSystem);
            }
            else
            {
                this->mLabel = "";
                this->mFileSystem = "UNKOWN";
            }


            //Get the Drives Type
            UINT iDriveType = GetDriveType(RootPath);

            switch(iDriveType)
            {
            case DRIVE_UNKNOWN:
                this->mType = "DRIVE_UNKNOWN";
                this->mTypeInt = 0;
                break;

            case DRIVE_NO_ROOT_DIR:
                this->mType = "DRIVE_NO_ROOT_DIR";
                this->mTypeInt = 1;
                break;

            case DRIVE_REMOVABLE:
                this->mType = "DRIVE_REMOVABLE";
                this->mTypeInt = 2;
                break;

            case DRIVE_FIXED:
                this->mType = "DRIVE_FIXED";
                this->mTypeInt = 3;
                break;

            case DRIVE_REMOTE:
                this->mType = "DRIVE_REMOTE";
                this->mTypeInt = 4;
                break;

            case DRIVE_CDROM:
                this->mType = "DRIVE_CDROM";
                this->mTypeInt = 5;
                break;

            case DRIVE_RAMDISK:
                this->mType = "DRIVE_RAMDISK";
                this->mTypeInt = 6;
                break;

            default:
                this->mType = "DRIVE_UNKNOWN";
                this->mTypeInt = 0;
                break;
            }

            // get the disk free space
            unsigned __int64 i64FreeBytesToCaller,i64TotalBytes,i64FreeBytes;
            lResult = GetDiskFreeSpaceEx(RootPath, (PULARGE_INTEGER)&i64FreeBytesToCaller, (PULARGE_INTEGER)&i64TotalBytes, (PULARGE_INTEGER)&i64FreeBytes);
            if(lResult)
            {
                mFreeBytesAvailable = i64FreeBytesToCaller;
                mTotalNumberOfBytes = i64TotalBytes;
                mTotalNumberOfFreeBytes = i64FreeBytes;
            }
            else
            {
                mFreeBytesAvailable = 0;
                mTotalNumberOfBytes = 0;
                mTotalNumberOfFreeBytes = 0;
            }

            //int mMegabyte = 1024*1024;
            //int mGigabyte = 1024*1024*1024;
            //printf ("Available space to caller = %I64u MB\n",i64FreeBytesToCaller / mMegabyte);
            //printf ("Total space = %I64u MB\n",i64TotalBytes / mMegabyte);
            //printf ("Free space on drive = %I64u MB\n",i64FreeBytes / mMegabyte);

            delete[] pLabel;
            delete[] pFileSystem;
        }

        //Returns a QStringList filled with Logical Drive Names
        QStringList VDrives::getLogicalDrives()
        {
            QStringList mList;
            DWORD lResult;
            DWORD dwSize = 1024;
            WCHAR* pBuffer = new WCHAR[dwSize];
            lResult = GetLogicalDriveStrings(dwSize,pBuffer);
            WCHAR* mItems = pBuffer;

            while(*mItems != '\0')
            {
                //mItems is the current string
                QString mRet = VQTConvert::WCHAR_to_QString(mItems);
                mList.append(mRet);
                mItems = mItems + lstrlen(mItems); // pStr now points to null at end of string
                mItems++; // pStr now points to the next string, or the second null to terminate
            }

            delete[] pBuffer;

            return mList;
        }

        //Returns a QString representing the drive type
        QString VDrives::DriveType()
        {
            return this->mType;
        }

        //Returns a Int representing the drive type
        int VDrives::DriveTypeInt()
        {
            return this->mTypeInt;
        }

        //Returns a QString representing the drive label
        QString VDrives::Label()
        {
            return this->mLabel;
        }

        //Returns a QString representing the drive name
        QString VDrives::Name()
        {
            return this->mDrive;
        }

        //Returns a QString representing the drive file system
        QString VDrives::FileSystem()
        {
            return this->mFileSystem;
        }

        //Returns a quint64 with the number of free bytes available
        quint64 VDrives::FreeBytesAvailable()
        {
            return this->mFreeBytesAvailable;
        }

        //Returns a quint64 with the total size in bytes
        quint64 VDrives::TotalNumberOfBytes()
        {
            return this->mTotalNumberOfBytes;
        }

        //Returns a quint64 with the number of free bytes
        quint64 VDrives::TotalNumberOfFreeBytes()
        {
            return this->mTotalNumberOfFreeBytes;
        }
        quint64 VDrives::VolumeSerialNumber()
        {
            return this->mVolumeSerialNumber;
        }



    } //end voidrealms::win32 namespace
} //end voidrealms namespace
